// --- Copyright (c) 2006-2008 Stefan Kyntchev ---
// This software is written and copyrighted by Stefan Kyntchev 
// and BeyondPod Team members. All rights are reserved.
// Author contact: support@beyondpod.mobi
// ------------------------------------------------------------------------
// This file is part of BeyondPod RSS Feed Reader and Podcast manager
// (www.codeplex.com/BeyondPod) 
// BeyondPod is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// BeyondPod is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
//  
// You should have received a copy of the GNU General Public License
// along with BeyondPod. If not, see <http://www.gnu.org/licenses/>
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.Collections.Generic;
using svs.Mobile.BeyondMedia.FeedCore.Helpers;
using svs.Mobile.BeyondMedia.FeedCore.RSS.Aggregators;

namespace svs.Mobile.BeyondMedia.FeedCore.RSS.Entities
{
	/// <summary>
	/// Describes an RSS feed
	/// </summary>
	public class RssFeed
	{
		public const string IMG_ITUNES_KEY = "itunes";
		public const string IMG_RSS_KEY = "rss";
		public const string IMG_RSS_CONTENT = "content";

		private readonly List<RssFeedItem> m_items;
		private Dictionary<string,string> m_feedImageLinks = new Dictionary<string,string>();
		private Guid m_feedID;

		public RssFeed()
		{
			Title = String.Empty;
			Link = String.Empty;
			Description = String.Empty;
			PubDate = null;
			m_items = new List<RssFeedItem>();
			Ttl = null;
		}

		/// <summary>
		/// Collection of the feed items
		/// </summary>
		public List<RssFeedItem> Items
		{
			get { return m_items; }
		}

		/// <summary>
		/// Name as it should apper to end users
		/// </summary>
		public string Title { get; set; }

		/// <summary>
		/// The URL that leads to the Web site of the channel
		/// </summary>
		public string Link { get; set; }

		/// <summary>
		/// A brief narrative about the contents of the channel
		/// </summary>
		public string Description { get; set; }

		public CategoryAggregate AggregateInfo { get; set; }

		/// <summary>
		/// Time date the channel was published in UTC
		/// </summary>
		public DateTime? PubDate { get; set; }

		/// <summary>
		/// Time to Live - number of minutes to cache the feed.
		/// </summary>
		public int? Ttl { get; set; }

		/// <summary>
		/// The date the feed was last retrieved (In UTC)
		/// </summary>
		public DateTime LastRetrievalDate { get; set; }

		/// <summary>
		/// True if the feed is old (and needs to be refreshed)
		/// </summary>
		public bool IsOld
		{
			get
			{
				int ttl = Ttl.HasValue ? (int) Ttl : 24*60;

				TimeSpan minutesOld = DateTime.UtcNow - LastRetrievalDate;

				return minutesOld.TotalMinutes > ttl;
			}
		}

		/// <summary>
		/// Number of days the feed is old
		/// </summary>
		public int DaysOld
		{
			get
			{
				return (int) (DateTime.UtcNow - LastRetrievalDate).TotalDays;
			}
		}

		/// <summary>
		/// ID of the Feed in the feed repository that corresponds to this feed content
		/// </summary>
		public Guid FeedID
		{
			get
			{
				return m_feedID;
			}
			set
			{
				m_feedID = value;
			}
		}

		/// <summary>
		/// Link to the feed images
		/// </summary>
		public Dictionary<string, string> FeedImageLinks
		{
			get { return m_feedImageLinks; }
			set { m_feedImageLinks = value; }
		}

		/// <summary>
		/// Returns the preffered Image link
		/// </summary>
		public string FeedImageLink
		{
			get
			{
				if (m_feedImageLinks.ContainsKey(IMG_RSS_KEY))
					return m_feedImageLinks[IMG_RSS_KEY];

				if (m_feedImageLinks.ContainsKey(IMG_ITUNES_KEY))
					return m_feedImageLinks[IMG_ITUNES_KEY];

				return null;
			}
		}

		public bool IsAggregateFeed
		{
			get { return AggregateInfo != null; }
		}

		/// <summary>
		/// Finds an eclosure given enclosure URL
		/// </summary>
		/// <param name="enclUrl"></param>
		/// <returns></returns>
		public RssEnclosure GetEnclosureByUrl(string enclUrl)
		{
			foreach (RssFeedItem item in Items)
			{
				if (item.Enclosure == null)
					continue;

				string iurl = HttpUtility.UrlDecode(item.Enclosure.Url);
				string eurl = HttpUtility.UrlDecode(enclUrl);

				if (item.Enclosure != null &&
				    string.Compare(iurl, eurl, StringComparison.InvariantCultureIgnoreCase) == 0)
				{
					return item.Enclosure;
				}
			}

			return null;
		}

		public RssEnclosure GetEnclosureByLocalFileName(string path)
		{
			foreach (var item in Items)
			{
				if (item.Enclosure == null)
					continue;

				if (string.Compare(item.Enclosure.LocalFileName, path, StringComparison.InvariantCultureIgnoreCase) == 0)
				{
					return item.Enclosure;
				}
			}

			return null;
		}

		/// <summary>
		/// Generates a list of Enclosures that are not downloaded and not in the history
		/// </summary>
		/// <returns></returns>
		public List<RssEnclosure> GetDownloadableEnclosures()
		{
			var retVal = new List<RssEnclosure>();

			foreach (RssFeedItem item in Items)
			{
				if (item.Enclosure != null && !item.Enclosure.Downloaded && !item.Enclosure.EnclosureInHistory)
					retVal.Add(item.Enclosure);
			}

			return retVal;
		}

		/// <summary>
		/// Generates a list of the X most recent downloadable enclosures 
		/// </summary>
		/// <returns></returns>
		public List<RssEnclosure> GetDownloadableEnclosures(int recentX)
		{
			var retVal = new List<RssEnclosure>();

			if (recentX <= 0)
				return retVal;

			foreach (RssFeedItem item in Items)
			{
				if (item.Enclosure != null)
				{
					if (!item.Enclosure.Downloaded && !item.Enclosure.EnclosureInHistory)
						retVal.Add(item.Enclosure);

					if (--recentX == 0)
						break;
				}
			}

			return retVal;
		}

		/// <summary>
		/// Locates an item by Item ID
		/// </summary>
		/// <param name="ItemID"></param>
		/// <returns></returns>
		public RssFeedItem GetItemById(int ItemID)
		{
			foreach (RssFeedItem item in Items)
			{
				if(item.ItemID.HasValue && item.ItemID.Equals(ItemID))
					return item;
			}

			return null;
		}

		public bool AreAllItemsRead()
		{
				foreach (RssFeedItem item in Items)
				{
					if(!item.Read)
						return false;
				}

				return true;
		}

		public void SetAllItemsAsRead()
		{
			ItemReadHistory.AddAllItems(this);
			
			if(!IsAggregateFeed)
				SyncOwnerFeedReadStatus();
			else
			{
				foreach (var feed in GetAllOriginatingFeeds())
				{
					RssFeedCache.SyncFeedReadStatus(feed);
				}
			}
		}

		public FeedList GetAllOriginatingFeeds()
		{
			var retVal = new FeedList();

			foreach (var item in Items)
			{
				var f = FeedRepository.GetFeedById(item.OriginatingFeedID);
				if (f != null && ! retVal.Contains(f))
				{
					retVal.Add(f);
				}
					
			}

			return retVal;
		}

		public void SyncOwnerFeedReadStatus()
		{
			var owner = FeedRepository.GetFeedById(m_feedID);
			if (owner != null)
				owner.HasUnreadItems = !AreAllItemsRead();
		}


	}
}